import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import mplfinance as mpf
from datetime import datetime
import warnings
warnings.filterwarnings('ignore')

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

print("=== 任务1：数据读取与基本信息 ===")
# 读取Excel文件
df = pd.read_excel('比亚迪后复权历史行情数据.xlsx')

# 观察数据形状
print(f"数据形状: {df.shape}")
print(f"行数: {df.shape[0]}")
print(f"列数: {df.shape[1]}")

# 查看实际的列名（去除可能的空格）
print("\n实际列名:")
for i, col in enumerate(df.columns):
    print(f"{i}: '{col}'")

# 去除列名中的空格和不可见字符
new_cols = {col: ''.join(c for c in col if c.isprintable()).strip() for col in df.columns}
df = df.rename(columns=new_cols)

print("\n清理后的列名:")
for i, col in enumerate(df.columns):
    print(f"{i}: '{col}'")

# 输出数据前5行
print("\n数据前5行:")
print(df.head())

# 查看数据列名和数据类型
print("\n数据列信息:")
print(df.info())

# 对定量变量进行描述性分析
print("\n定量变量描述性分析:")
print(df.describe())

print("\n=== 任务2：相关性分析 ===")
# 选择数值列进行相关性分析
numeric_cols = df.select_dtypes(include=[np.number]).columns
print(f"用于相关性分析的数值列: {list(numeric_cols)}")

# 计算相关系数
corr_matrix = df[numeric_cols].corr()
print("\n相关系数矩阵:")
print(corr_matrix.round(4))

# 绘制相关系数热力图
plt.figure(figsize=(12, 8))
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', linewidths=0.5, fmt='.4f')
plt.title('比亚迪股票各变量间相关系数热力图')
plt.tight_layout()
plt.savefig('相关系数热力图.png', dpi=300)
print("\n相关系数热力图已保存为 '相关系数热力图.png'")

print("\n=== 任务3：2023年收盘价时序图 ===")
# 查找日期列和收盘价列
print("\n查找关键字匹配的列:")
date_cols = [col for col in df.columns if any(keyword in col.lower() for keyword in ['日期', 'date', '时间', 'time'])]
close_cols = [col for col in df.columns if any(keyword in col.lower() for keyword in ['收盘', 'close', '收盘价'])]
open_cols = [col for col in df.columns if any(keyword in col.lower() for keyword in ['开盘', 'open', '开盘价'])]
high_cols = [col for col in df.columns if any(keyword in col.lower() for keyword in ['最高', 'high', '最高价'])]
low_cols = [col for col in df.columns if any(keyword in col.lower() for keyword in ['最低', 'low', '最低价'])]
volume_cols = [col for col in df.columns if any(keyword in col.lower() for keyword in ['成交量', 'volume', '成交'])]

print(f"可能的日期列: {date_cols}")
print(f"可能的收盘价列: {close_cols}")
print(f"可能的开盘价列: {open_cols}")
print(f"可能的最高价列: {high_cols}")
print(f"可能的最低价列: {low_cols}")
print(f"可能的成交量列: {volume_cols}")

# 使用找到的列进行分析
date_col = date_cols[0] if date_cols else df.columns[0]
close_col = close_cols[0] if close_cols else [col for col in numeric_cols if '价' in col or 'price' in col.lower()][-1]

print(f"\n使用的日期列: '{date_col}'")
print(f"使用的收盘价列: '{close_col}'")

# 确保日期列为datetime类型
df[date_col] = pd.to_datetime(df[date_col], errors='coerce')

# 筛选2023年数据
df_2023 = df[df[date_col].dt.year == 2023].copy()
df_2023 = df_2023.sort_values(date_col)

print(f"2023年数据量: {len(df_2023)} 条")
print(f"2023年数据时间范围: {df_2023[date_col].min()} 至 {df_2023[date_col].max()}")

# 绘制收盘价时序图
plt.figure(figsize=(14, 7))
plt.plot(df_2023[date_col], df_2023[close_col], marker='', linewidth=2, color='#1f77b4')
plt.title('比亚迪2023年收盘价走势')
plt.xlabel('日期')
plt.ylabel('收盘价')
plt.grid(True, alpha=0.3)
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig('2023年收盘价走势图.png', dpi=300)
print("2023年收盘价时序图已保存为 '2023年收盘价走势图.png'")

print("\n=== 任务4：2023年4-6月K线图 ===")
# 筛选2023年4月到6月的数据
df_2023_4_6 = df_2023[(df_2023[date_col] >= '2023-04-01') & (df_2023[date_col] <= '2023-06-30')].copy()
print(f"2023年4-6月数据量: {len(df_2023_4_6)} 条")

if len(df_2023_4_6) > 0:
    # 确定K线图所需列
    open_col = open_cols[0] if open_cols else [col for col in numeric_cols if '开盘' in col or 'open' in col.lower()][0] if [col for col in numeric_cols if '开盘' in col or 'open' in col.lower()] else numeric_cols[1]
    high_col = high_cols[0] if high_cols else [col for col in numeric_cols if '最高' in col or 'high' in col.lower()][0] if [col for col in numeric_cols if '最高' in col or 'high' in col.lower()] else numeric_cols[2]
    low_col = low_cols[0] if low_cols else [col for col in numeric_cols if '最低' in col or 'low' in col.lower()][0] if [col for col in numeric_cols if '最低' in col or 'low' in col.lower()] else numeric_cols[3]
    
    print(f"使用的开盘价列: '{open_col}'")
    print(f"使用的最高价列: '{high_col}'")
    print(f"使用的最低价列: '{low_col}'")
    print(f"使用的收盘价列: '{close_col}'")
    
    # 准备K线图数据
    kline_data = df_2023_4_6.set_index(date_col)
    kline_data = kline_data[[open_col, high_col, low_col, close_col]]
    kline_data.columns = ['Open', 'High', 'Low', 'Close']  # 重命名为mplfinance需要的列名
    
    # 添加成交量（如果有）
    volume_data = None
    if volume_cols:
        volume_col = volume_cols[0]
        kline_data['Volume'] = df_2023_4_6[volume_col].values
        print(f"使用的成交量列: '{volume_col}'")
    
    # 绘制K线图
    mpf.plot(kline_data, 
            type='candle',
            title='比亚迪2023年4-6月K线图',
            ylabel='价格',
            style='yahoo',
            figratio=(16, 9),
            volume=True if volume_cols else False,
            savefig='2023年4-6月K线图.png')
    
    print("2023年4-6月K线图已保存为 '2023年4-6月K线图.png'")
    
    # K线图分析
    print("\nK线图分析:")
    print(f"分析期间: 2023年4月1日至2023年6月30日")
    print(f"开盘价范围: {kline_data['Open'].min():.2f} - {kline_data['Open'].max():.2f}")
    print(f"收盘价范围: {kline_data['Close'].min():.2f} - {kline_data['Close'].max():.2f}")
    print(f"最高价范围: {kline_data['High'].min():.2f} - {kline_data['High'].max():.2f}")
    print(f"最低价范围: {kline_data['Low'].min():.2f} - {kline_data['Low'].max():.2f}")
    
    # 计算一些基本统计
    price_change = kline_data['Close'].iloc[-1] - kline_data['Close'].iloc[0]
    price_change_pct = (price_change / kline_data['Close'].iloc[0]) * 100
    print(f"期间价格变化: {price_change:.2f} ({price_change_pct:.2f}%)")
    
    # 计算波动率
    daily_returns = kline_data['Close'].pct_change().dropna()
    volatility = daily_returns.std() * np.sqrt(252)  # 年化波动率
    print(f"日收益率波动率: {daily_returns.std():.4f}")
    print(f"年化波动率: {volatility:.4f}")
    
    # 识别趋势
    if price_change_pct > 5:
        trend = "上涨趋势"
    elif price_change_pct < -5:
        trend = "下跌趋势"
    else:
        trend = "震荡走势"
    print(f"整体趋势判断: {trend}")
else:
    print("未找到2023年4-6月的数据")

print("\n=== 分析完成 ===")
print("生成的图表文件:")
print("1. 相关系数热力图.png")
print("2. 2023年收盘价走势图.png")
print("3. 2023年4-6月K线图.png")